home *** CD-ROM | disk | FTP | other *** search
/ Language/OS - Multiplatform Resource Library / LANGUAGE OS.iso / lisp / kcl / akcl / akcl1615.lha / c / sfasl.c.prev < prev    next >
Text File  |  1990-02-05  |  16KB  |  640 lines

  1.  
  2. /* 
  3. Copyright William Schelter. All rights reserved.
  4. There is a companion file rsym.c which is used to build
  5. a list of the external symbols in a COFF or A.OUT object file, for
  6. example saved_kcl.  These are loaded into kcl, and the
  7. linking is done directly inside kcl.  This saves a good 
  8. deal of time.   For example a tiny file foo.o with one definition
  9. can be loaded in .04 seconds.  This is much faster than
  10. previously possible in kcl.
  11. The function fasload from unixfasl.c is replaced by the fasload
  12. in this file.
  13. this file is included in unixfasl.c
  14. via #include "../c/sfasl.c" 
  15. */
  16. #include <varargs.h>
  17.  
  18.  
  19. /* for testing in standalone manner define STAND
  20.  You may then compile this file cc -g -DSTAND -DDEBUG -I../hn
  21.  a.out /tmp/foo.o /public/akcl/unixport/saved_kcl /public/akcl/unixport/
  22.  will write a /tmp/sfasltest file
  23.  which you can use comp to compare with one produced by ld.
  24.  */
  25.  
  26.  
  27. #ifdef STAND
  28. #include "config.h"
  29. #include <stdio.h>
  30. #include "mdefs.h"
  31.  
  32. #else
  33. #include "include.h"
  34. #undef S_DATA
  35. #endif
  36.  
  37. #include "ext_sym.h"
  38.  
  39. int node_compare();
  40. char *malloc();
  41. char *the_start;
  42. char *bsearch();
  43.  
  44. struct reloc relocation_info;
  45. /* next 5 static after debug */
  46.  
  47. int debug;
  48.  
  49. #ifdef DEBUG
  50. #define dprintf(s,ar) if(debug) { printf(" ( s )",ar) ; fflush(stdout);}
  51. #define STAT
  52.  
  53. #else /* end debug */
  54. #define dprintf(s,ar) 
  55. #define STAT static
  56. #endif
  57.  
  58.  
  59. #define MAXPATHLEN 200
  60. #define PTABLE_EXTRA 20
  61.  
  62. STAT struct syment *symbol_table;
  63. STAT char *start_address;
  64. STAT char *my_string_table;
  65. STAT int extra_bss;
  66.  
  67. STAT char command[200];
  68. STAT char tmpfile1 [50]; 
  69.  
  70. #ifndef describe_sym
  71. #define describe_sym(a)
  72. #endif
  73.  
  74. #ifdef STAND
  75. #include "rel_stand.c"
  76. #endif
  77.  
  78.  
  79. #define TEMPSPACE 50000
  80. char tempspace[TEMPSPACE];
  81. char *bil;
  82. char 
  83. *temp_malloc(n)
  84. unsigned int n; 
  85. {char *val;
  86.  val=(char *) (4*((((int)bil)+4)/4));
  87.  bil=val+n;
  88.  if (bil < tempspace +TEMPSPACE)
  89.    return val;
  90.  else {bil=val; 
  91.  dprintf( having to use regular malloc for %d,n);
  92.  return malloc(n);}
  93. }
  94.  
  95. #include RELOC_FILE
  96.  
  97. /* free up space which is not allocated in tempspace */
  98.  
  99. #define TEMP_FREE(x) \
  100. if (((char *)x)> tempspace+TEMPSPACE || ((char *)x)< tempspace) \
  101.      free(x)
  102.  
  103. int
  104. fasload(faslfile)
  105. object faslfile;
  106. {       long fasl_vector_start;
  107.     struct filehdr fileheader;
  108. #ifdef COFF
  109.     struct scnhdr sectionheader;
  110.         struct scnhdr section[4];
  111. #endif
  112.     int textsize, datasize, bsssize,nsyms;
  113.     int string_size=0;
  114.  
  115.     object memory, data;
  116.     FILE *fp;
  117.     char filename[MAXPATHLEN];
  118.     int i;
  119.     int init_address=0;
  120. #ifndef STAND    
  121.     object *old_vs_base = vs_base;
  122.     object *old_vs_top = vs_top;
  123. #endif
  124.       bil=tempspace; /* reset tmp malloc */
  125.     extra_bss=0;
  126. #ifdef STAND
  127.     strcpy(filename,faslfile);
  128.     fp=fopen(filename,RDONLY);
  129. #else
  130.     coerce_to_filename(faslfile, filename);
  131.     faslfile = open_stream(faslfile, smm_input, Cnil, Kerror);
  132.     vs_push(faslfile);
  133.     fp = faslfile->sm.sm_fp;
  134. #endif    
  135.  
  136.     HEADER_SEEK(fp);
  137.     if(!fread((char *)&fileheader, sizeof(struct filehdr), 1, fp))
  138.       FEerror("Could not get the header",0,0);
  139.     nsyms = NSYMS(fileheader);
  140. #ifdef COFF
  141.     fseek(fp,fileheader.f_opthdr,1);
  142.     fread(§ion[1], sizeof(sectionheader), 1, fp);
  143.         textsize = section[1].s_size;
  144.     fread((char *)§ion[2], sizeof(sectionheader), 1, fp);
  145.      datasize = section[2].s_size; 
  146.     fread(§ionheader, sizeof(sectionheader), 1, fp);
  147.     if (strcmp(section[3].s_name, ".bss") == 0)
  148.       bsssize=section[3].s_size; 
  149.     else     bsssize=section[3].s_size = 0;
  150. #endif
  151.  
  152. #ifdef BSD
  153.     textsize=fileheader.a_text;
  154.     datasize=fileheader.a_data;
  155.     bsssize=fileheader.a_bss;
  156. #endif
  157.     symbol_table =
  158.       (struct syment *) temp_malloc(sizeof(struct syment)*
  159.                     (unsigned int)nsyms);
  160.     fseek(fp,(int)( N_SYMOFF(fileheader)),  0);
  161.     {
  162.     for (i = 0;  i < nsyms;  i++)
  163.         {fread((char *)&symbol_table[i], SYMESZ, 1, fp);
  164.          dprintf( symbol table %d , i);
  165.          if (debug) describe_sym(i);
  166.          dprintf( at %d , &symbol_table[i]);
  167. #ifdef HPUX
  168.          symbol_table[i].n_un.n_strx = string_size;
  169.          dprintf(string_size %d, string_size);
  170.          string_size += symbol_table[i].n_length + 1;
  171.          fseek(fp,(int)symbol_table[i].n_length,1);
  172. #endif
  173.            }
  174.        }
  175. /*    
  176. on MP386
  177. The sizeof(struct syment) = 20, while only SYMESZ =18. So we had to read
  178. one at a time.
  179. fread((char *)symbol_table, SYMESZ*fileheader.f_nsyms,1,fp);
  180. */
  181.  
  182. #ifdef READ_IN_STRING_TABLE
  183.  
  184. my_string_table=READ_IN_STRING_TABLE(fp,string_size);
  185.  
  186. #else  
  187. #ifdef MUST_SEEK_TO_STROFF
  188.   fseek(fp,N_STROFF(fileheader),0);
  189. #endif    
  190.   {int ii=0;
  191.     if (!fread((char *)&ii,sizeof(int),1,fp))
  192.           {FEerror("The string table of this file did not have any length",0,
  193.            0);}
  194.         fseek(fp,-4,1);
  195.         /* at present the string table is located just after the symbols */
  196.         my_string_table=temp_malloc((unsigned int)ii);
  197.         dprintf( string table leng = %d, ii);
  198.  
  199.         if(ii!=fread(my_string_table,1,ii,fp))
  200.           FEerror("Could not read whole string table",0,0) ;
  201.     }
  202. #endif    
  203. #ifdef SEEK_TO_END_OFILE
  204. SEEK_TO_END_OFILE(fp);    
  205. #else    
  206.      while ((i = getc(fp)) == 0)
  207.         ;
  208.     ungetc(i, fp);
  209. #endif
  210.     
  211.     fasl_vector_start=ftell(fp);
  212.  
  213.    if (!((c_table.ptable) && *(c_table.ptable)))
  214.      build_symbol_table();
  215.  
  216. /* figure out if there is more bss space needed */
  217.     extra_bss=get_extra_bss(symbol_table,nsyms,datasize+textsize+bsssize,
  218.                 &init_address);
  219.     
  220. /* allocate some memory */
  221. #ifndef STAND    
  222.     memory = alloc_object(t_cfdata);
  223.     memory->cfd.cfd_self = 0;
  224.     memory->cfd.cfd_start = 0;
  225.     memory->cfd.cfd_size = datasize+textsize+bsssize + extra_bss;
  226.     vs_push(memory);
  227.         the_start=start_address=        
  228.      memory->cfd.cfd_start =    
  229.      alloc_contblock(memory->cfd.cfd_size);
  230.  
  231. #else
  232.     the_start=start_address
  233.       = malloc(datasize+textsize+bsssize + extra_bss + 0x80000);
  234.     the_start=start_address= (char *)(
  235.        0x1000* ((((int)the_start + 0x70000) + 0x1000)/0x1000));
  236.     
  237. #endif      
  238.     dprintf( code size %d , datasize+textsize+bsssize + extra_bss);
  239.     if (fseek(fp,N_TXTOFF(fileheader) ,0) < 0)
  240.         FEerror("file seek error",0,0);
  241.     fread(the_start, textsize + datasize, 1, fp);
  242.     dprintf(read into memory text +data %d bytes, textsize + datasize);
  243. /* relocate the actual loaded text  */
  244.  
  245.         dprintf( the_start %x, the_start);
  246.  
  247.     /* this looks up symbols in c.ptable and also adds new externals to
  248.        that c.table */
  249.     relocate_symbols(NSYMS(fileheader));  
  250.     
  251. #ifdef COFF
  252.   {int j=0;
  253.      for(j=1; j<3 ; j++)
  254.        { dprintf( relocating section %d \n,j);
  255.      fseek(fp,section[j].s_relptr,0);
  256.         for(i=0; i < section[j].s_nreloc; i++)
  257.       {fread(&relocation_info, 10, 1, fp);
  258.            dprintf(relocating %d,i);
  259.        relocate();};
  260.         }};
  261. #endif
  262. #ifdef BSD
  263.      fseek(fp,N_RELOFF(fileheader),0);
  264.     {int nrel = (fileheader.a_trsize/sizeof(struct reloc));
  265.      for (i=0; i < nrel; i++)
  266.        {fread((char *)&relocation_info, sizeof(struct reloc),
  267.             1, fp);
  268.           dprintf(relocating %d,i);
  269.           relocate();
  270.         }
  271.     }
  272. #ifdef N_DRELOFF
  273.      fseek (fp, N_DRELOFF(fileheader), 0);
  274. #endif
  275.      {int nrel = (fileheader.a_drsize/sizeof(struct reloc));
  276.       the_start += fileheader.a_text;
  277.      for (i=0; i < nrel; i++)
  278.  
  279.        {fread((char *)&relocation_info, sizeof(struct reloc),
  280.             1, fp);
  281.           dprintf(relocating %d,i);
  282.           relocate();
  283.         }
  284.        }
  285. #endif
  286.  
  287. /* end of relocation */
  288.        dprintf( END OF RELOCATION \n,0);
  289.        dprintf( invoking init function at %x, start_address)
  290.        dprintf( textsize is %x,textsize);
  291.        dprintf( datasize is %x,datasize);
  292.  
  293. /* read in the fasl vector */
  294.     fseek(fp,fasl_vector_start,0);
  295.         if (feof(fp))
  296.       {data=0;}
  297.          else{
  298.     data = read_fasl_vector(faslfile);
  299.     vs_push(data);
  300. #ifdef COFF
  301.        dprintf( read fasl now symbols %d , fileheader.f_nsyms);
  302. #endif
  303.     }
  304.     close_stream(faslfile, 1);    
  305.  
  306. /*
  307.  {
  308.     int fd;
  309.  
  310.     fd = creat ("xsakcl.bits", 0777);
  311.     write (fd, memory->cfd.cfd_start, textsize + datasize);
  312.     close (fd);
  313.  
  314.     fd = open ("xsl2.bits", 0);
  315.     read (fd, memory->cfd.cfd_start, memory->cfd.cfd_size);
  316.     close (fd);
  317.  }
  318. */
  319.  
  320. #ifndef STAND
  321.     TEMP_FREE(my_string_table);
  322.     TEMP_FREE(symbol_table);
  323.  
  324.     call_init(init_address,memory,data);
  325.     
  326.         vs_base = old_vs_base;
  327.     vs_top = old_vs_top;
  328.        if(symbol_value(Vload_verbose)!=Cnil)
  329.         printf("start address -T %x ",memory->cfd.cfd_start);
  330.     return(memory->cfd.cfd_size);
  331. #endif
  332.     {FILE *out;
  333.      out=fopen("/tmp/sfasltest","w");
  334.      fwrite((char *)&fileheader, sizeof(struct filehdr), 1, out);
  335.      fwrite(start_address,sizeof(char),datasize+textsize,out);
  336.      fclose(out);}
  337.      printf("\n(start %x)\n",start_address);
  338.  
  339. }
  340.         
  341. get_extra_bss(symbol_table,length,start,ptr)
  342. int length;
  343. struct syment *symbol_table;
  344. int *ptr;   /* store init address offset here */
  345. {int result = start;
  346.  struct syment *end,*sym;
  347.  char tem[SYMNMLEN +1];
  348.  end =symbol_table + length;
  349.  for(sym=symbol_table; sym < end; sym++)
  350.    {
  351. #ifdef FIND_INIT
  352. FIND_INIT
  353. #endif  
  354. #ifdef BSD
  355.      tem; /* ignored */
  356.      if(SYM_EXTERNAL_P(sym) && SYM_UNDEF_P(sym))
  357. #endif
  358. #ifdef COFF
  359.      if(0)
  360.      /* what we really want is
  361.     if (sym->n_scnum==0 && sym->n_sclass == C_EXT
  362.                         && !(bsearch(..in ptable for this symbol)))
  363.     Since this won't allow loading in of a new external array
  364.     char foo[10]  not ok
  365.     static foo[10] ok.
  366.     for the moment we give undefined symbol warning..
  367.     Should really go through the symbols, recording the external addr
  368.     for ones found in ptable, and for the ones not in ptable
  369.     set some flag, and add up the extra_bss required.  Then
  370.     when you have the new memory chunk in hand,
  371.     you could make the pass setting the relative addresses.
  372.     for the ones you flagged last time.
  373.     */
  374. #endif
  375.        /* external bss so not included in size of bss for file */
  376.        {int val=sym->n_value;
  377.     struct node joe;
  378.     if (val && c_table.ptable)
  379.       {joe.string=SYM_NAME(sym);
  380.        if(0==bsearch((char *)(&joe),(char*) (c_table.ptable),
  381.              c_table.length,
  382.              sizeof(struct node), node_compare))
  383.        { sym->n_value=result;
  384.          result += val;}}}
  385.      
  386.      sym += NUM_AUX(sym); 
  387.  
  388.    }
  389.  return (result-start);
  390. }
  391.  
  392.  
  393.  
  394. /* go through the symbol table changing the addresses of the symbols
  395. to reflect the current cfd_start */
  396.  
  397. relocate_symbols(length)
  398. unsigned int length;
  399. {struct syment *end,*sym;
  400.  unsigned int typ;
  401.  char *str;
  402.  char tem[SYMNMLEN +1];
  403.  tem[SYMNMLEN]=0;
  404.  end =symbol_table + length;
  405.  for(sym=symbol_table; sym < end; sym++) {
  406.     typ=NTYPE(sym);
  407. #ifdef BSD
  408. #ifdef N_STAB    
  409.     if (N_STAB & sym->n_type) continue;/* skip: It  is for dbx only */
  410. #endif    
  411.     typ=N_SECTION(sym);
  412. /* if(sym->n_type  &  N_EXT) should add the symbol name,
  413.    so it would be accessible by future loads  */
  414. #endif
  415.    switch (typ)    {
  416. #ifdef BSD
  417.    case N_ABS : case N_TEXT: case N_DATA: case N_BSS:
  418. #endif
  419. #ifdef COFF
  420.    case 1: case 2: case 3:
  421. #endif
  422.      str=SYM_NAME(sym);
  423.      dprintf( for sym %s ,str)
  424.      dprintf( new value will be start %x, start_address);
  425.      sym->n_value = (int)start_address;
  426.      break;
  427.    case  N_UNDEF:
  428.      str=SYM_NAME(sym);
  429.      dprintf( undef symbol %s ,str);    
  430.      dprintf( symbol diff %d , sym - symbol_table);
  431.      describe_sym(sym-symbol_table);
  432.      set_symbol_address(sym,str);
  433.      describe_sym(sym-symbol_table);
  434.      break;
  435.    default:
  436. #ifdef COFF
  437.      dprintf(am ignoring a scnum %d,(sym->n_scnum));
  438. #endif
  439.      break;
  440.    }
  441.    sym += NUM_AUX(sym);
  442.  }
  443. }
  444.  
  445. /* 
  446. STEPS:
  447. 1) read in the symbol table from the file,
  448. 2) go through the symbol table, relocating external entries.
  449. 3) for i <=2 go thru the relocation information for this section
  450.  relocating the text.
  451. 4) done.
  452. */
  453.  
  454. set_symbol_address(sym,string)
  455. struct syment *sym;
  456. char *string;
  457. {struct node *answ,joe;
  458.  if (c_table.ptable)
  459.     {joe.string=string;
  460.      dprintf(string %s, string);
  461.      
  462.     answ = (struct node *)bsearch((char *)(&joe),(char*) (c_table.ptable),
  463.                   c_table.length,
  464.                    sizeof(struct node), node_compare);
  465.      dprintf(answ %d , (answ ? answ->address : -1));
  466.     if(answ)
  467.      {
  468. #ifdef COFF
  469.       sym->n_value = answ->address - sym->n_value;
  470. #endif
  471. #ifdef BSD
  472.       /* the old value of sym->n_value is the length of the common area
  473.      starting at this address */
  474.       sym->n_value = answ->address;
  475. #endif
  476. }      
  477.      else
  478.       {
  479.  
  480. #ifdef BSD
  481.     {char *name;
  482.      name=malloc(1+strlen(string));
  483.      strcpy(name,string);
  484.      sym->n_value = sym->n_value + (unsigned int) the_start;
  485.      add_symbol(string,sym->n_value,NULL);
  486.        }
  487. #endif
  488.      fprintf(stdout,"undefined %s symbol",string)
  489.       ;fflush(stdout);
  490.      
  491.    }}
  492.  
  493.     else{FEerror("symbol table not loaded",0,0);}}
  494.  
  495. /*
  496. #define ADD_SYMBOL(name) add_symbol("name",(int) &(name),0)
  497. Use the add_symbol to add a c symbol, which you want to refer
  498. to in subsequent loads.  The address used in subsequent loads,
  499. will be the load address of the current symbol.
  500. Such a symbol may only be added once, since subsequent references
  501. will try to link to the old address.
  502. */
  503.  
  504. build_symbol_table()
  505. {  printf("Building symbol table for %s ..\n",kcl_self);fflush(stdout);
  506.    sprintf(tmpfile1,"/tmp/rsym%d",getpid());
  507.    coerce_to_filename(symbol_value(siVsystem_directory),
  508.               system_directory);
  509.    sprintf(command,"%srsym %s %s",system_directory,kcl_self,tmpfile1);
  510.    if (system(command) != 0)
  511.      FEerror("The rsym command ~a failed .",1,make_simple_string(command)
  512.          );
  513.    read_special_symbols(tmpfile1);
  514.    unlink(tmpfile1);
  515.    dprintf(c_table %d , c_table.length);
  516.    qsort((char*)(c_table.ptable),(int)(c_table.length),sizeof(struct node),node_compare);
  517.  }
  518.  
  519.  
  520.  
  521. /*to do:Addition of one symbol to the ptable is very slow, because we 
  522. sort each time! */
  523.  
  524. add_symbol(va_alist)
  525.      va_dcl
  526. {char *string;
  527.  int address;
  528.  struct node joe;
  529.  int nstr,i;
  530.  va_list ap;
  531.  
  532.   /* terminate arg list with NULL pointer */
  533.  
  534.  if(!(c_table.ptable)) return ; /* this is in a function before ptable is init */
  535.  nstr=0;
  536.  /* count the number of strings */
  537.  
  538.  va_start(ap);
  539.  while (va_arg(ap,char*)!=0) 
  540.    { nstr++;
  541.      va_arg(ap,int);
  542.      if (nstr >1000) FEerror("Did you really give 1000 strings or just forget 0 ending",0,0);};
  543.  va_end(ap);
  544.  
  545.  va_start(ap);
  546.  if (( int)((c_table.alloc_length) - (c_table.length)) -nstr>0)
  547.    { 
  548.    BEGIN:
  549.      for(i=0;i<2*nstr;i=i+2)
  550.        { string=va_arg(ap,char *);
  551.      joe.string=string;
  552.      if(bsearch((char *)(&joe),(char*) (c_table.ptable),(c_table.length),
  553.             sizeof(struct node), node_compare))
  554.        {FEerror("The string ~a is already in the ptable",1,
  555.             make_simple_string(string));};
  556.      {struct node *u;
  557.       u= ((*(c_table.ptable))+((c_table.length)+(i/2)));
  558.       u->string = string;
  559.       u->address = va_arg(ap,int);}
  560.        }
  561.      (c_table.length)=(c_table.length)+nstr;
  562.      qsort((char*)(c_table.ptable),(int)(c_table.length),sizeof(struct node),node_compare);
  563.    }
  564.  else 
  565.    /* grow the ptable */
  566.    { TABL *new, *old_pt;
  567.      new=
  568.       (TABL *)malloc(sizeof(struct node)
  569.          *((c_table.alloc_length)=((c_table.length) + nstr + PTABLE_EXTRA)));
  570.      old_pt=(c_table.ptable);
  571.      /* copy it */
  572.      {register int i ;
  573.       for (i=0; i < c_table.length; i++)
  574.     {(*new)[i].string=(*old_pt)[i].string;
  575.      (*new)[i].address=(*old_pt)[i].address;}}
  576.      
  577.      (c_table.ptable)=new; 
  578.      free((char *)old_pt);
  579.      goto BEGIN ;
  580.    }
  581.  va_end(ap);
  582.  
  583.  
  584.  /* this is in fat_string.c for the moment */
  585. /*
  586. read_special_symbols(symfile)
  587. char *symfile;
  588. {FILE *symin;
  589.  char *symbols;
  590.  int i,jj;
  591.  struct lsymbol_table tab;
  592.  if (!(symin=fopen(symfile,"r")))
  593.    {perror(symfile);exit(1);};
  594.  fread((char *)&tab,sizeof(tab),1,symin);
  595.  symbols=malloc(tab.tot_leng);
  596.  c_table.alloc_length=( (PTABLE_EXTRA+ tab.n_symbols));
  597.  c_table.ptable =(TABL *)malloc(sizeof(struct node) * (c_table.alloc_length));
  598.  if (!(c_table.ptable)) {perror("could not allocate"); exit(1);};
  599.  i=0;
  600.  c_table.length = tab.n_symbols;
  601.  while(i < tab.n_symbols)
  602.    { fread((char *)&jj,sizeof(int),1,symin);
  603.      (SYM_ADDRESS(c_table,i))=jj;
  604.      SYM_STRING(c_table,i)=symbols;
  605.  
  606.      while( *(symbols++) =   getc(symin)) 
  607.        {;}
  608.      dprintf( name %s ,  SYM_STRING(c_table,i));
  609.      dprintf( address %d , jj);
  610.      i++;
  611.    }
  612.  
  613. }
  614.  
  615. */
  616.  
  617. #ifdef DEBUG
  618. print_name(p)
  619.      struct syment *p;
  620. {char tem[10],*name;
  621.  name=SYM_NAME(p);
  622.  name=   (((p)->_n._n_n._n_zeroes == 0) ? 
  623.         &my_string_table[(p)->_n._n_n._n_offset] :
  624.                ((p)->_n._n_name[SYMNMLEN -1] ? 
  625.                  (strncpy(tem,(p)->_n._n_name,  
  626.                        SYMNMLEN), 
  627.                   (char *)tem) : 
  628.                   (p)->_n._n_name ));
  629.  
  630.  printf("(name:|%s|)",name);
  631.  printf("(sclass 0x%x)",p->n_sclass);
  632.   printf("(external_p 0x%x)",SYM_EXTERNAL_P(p));
  633.  printf("(n_type 0x%x)",p->n_type);
  634.  printf("(n_value 0x%x)",p->n_value);
  635.  printf("(numaux 0x%x)\n",NUM_AUX(p));
  636.  fflush(stdout);
  637. }
  638. #endif
  639.